package com.PuzGame.combinenumbers;

import java.util.ArrayList;
import java.util.Random;
import java.util.Stack;

import android.util.Log;

public class LevelGenerator {
	
	public static Random rand = new Random();
	
	public static long RandomNumber(long max)
	{    
	    return RandomNumber(0, max);
	}
	
	public static long RandomNumber(long min, long max)
	{
		Log.i("RandomNumber", "min: "+min+" max: "+max);
		max =  Math.min(max, (long)Math.sqrt(10000000)-1);
		if(max == min)
		{
			return max;
		}
		
		if(max ==0)
		{
			max=1;
		}
		
		rand.setSeed(rand.nextLong());
		
		long randlong = rand.nextLong();
		randlong %= (long)(Math.abs(max) - min+1);
		
		if(randlong>=0)
			randlong +=min;
		else
			randlong -=min;
				
		return randlong;		
		
		
	    //int randomNum = rand.nextInt((Math.abs(max) - min) + 1) + min;
	    
	    //return randomNum;
	}
	
	public static ArrayList<Long> RandomList(int qty, long max)
	{
		
		ArrayList<Long> list = new ArrayList<Long>();
		
		for (int i = 0; i < qty; i++)
		{
			list.add(RandomNumber(max));
		}

	    return list;
	}
	
	private static String OpToString(int op)
	{
		switch (op) {
		case 0:
			return "+";
		case 1:
			return "-";
		case 2:
			return "X";
		case 3:
			return "/";

		default:
			return "?";
		}
	}
	
	public static ArrayList<Long> ListFromGoal(int qty, long Goal, StringBuilder solution)
	{
		Stack<String> solStack = new Stack<String>();
		ArrayList<Long> list = new ArrayList<Long>();
		long TempGoal = Goal;
		for (int i = 0; i < qty-1; i++)
		{
			long temp;
			int op = (int) (RandomNumber(200)%4);
			op = Math.abs(op);
			Log.i("RandomNumber", "op: "+op);
			if (op == 0)
			{
				temp = RandomNumber(1,(long)(Math.max(10,TempGoal*0.6)));
				list.add(temp);
				solStack.add(Long.toString(temp)+"@");
				solStack.add(OpToString(op)+"@");
				TempGoal -= temp;
			} 
			else if (op == 1)
			{
				temp = RandomNumber(1,(long)(Math.max(10,TempGoal*0.6)));
				list.add(temp);
				solStack.add(Long.toString(temp)+"@");
				solStack.add(OpToString(op)+"@");
				TempGoal += temp;
			}
			else if (op == 2)
			{
				if (TempGoal == 0)
				{
					temp = RandomNumber(1,(long)(Math.max(10,TempGoal*0.6)));
					list.add(temp);
					solStack.add(Long.toString(temp)+"@");
					solStack.add(OpToString(op)+"@");
				}
				else if (isPrime(Math.abs(TempGoal)) || Math.abs(TempGoal)==1)
				{
					i--;
					continue;
				}
				else
				{
					
					ArrayList<Long> Factors = getfactors(Math.abs(TempGoal));
					
					if(qty - i >= 4 && Math.abs(TempGoal) > 10 )//&& 3 == Math.abs(RandomNumber(0,(long)(4))))
					{
						temp = RandomNumber(2,(long)TempGoal-1);
						if(Factors.contains(temp))
						{
							list.add(temp);
							solStack.add(Long.toString(temp)+"@");
							solStack.add(OpToString(op)+"@");
							TempGoal /= temp;
						}
						else
						{
							RationalNumber
							rn = new RationalNumber(TempGoal, temp);
							list.add(rn.getNumerator()/rn.getDenominator());
							i++;
							list.add(rn.getNumerator()%rn.getDenominator());
							i++;
							list.add(rn.getDenominator());
							
							solStack.add("("+"@"+rn.getNumerator()%rn.getDenominator()+"@"+"/"+"@"+rn.getDenominator()+"@"+"+"+"@"+rn.getNumerator()/rn.getDenominator()+"@"+")"+"@");
							solStack.add(OpToString(op)+"@");
							
							TempGoal = temp;
						}
					}
					else
					{
						int RandIndex = (int) RandomNumber(0,(long)(Factors.size()-1));
						RandIndex = Math.abs(RandIndex);
						temp = Factors.get(RandIndex);
						list.add(temp);
						solStack.add(Long.toString(temp)+"@");
						solStack.add(OpToString(op)+"@");
						TempGoal /= temp;
					}
				}
			}
			else if (op == 3)
			{
				temp = RandomNumber(1,(long)(Math.max(10,TempGoal*0.6)));
				list.add(temp);
				solStack.add(Long.toString(temp)+"@");
				solStack.add(OpToString(op)+"@");
				TempGoal *= temp;
			}
			
		}
		list.add(TempGoal);
		solStack.add(Long.toString(TempGoal)+"@");

		while (!solStack.empty())
		{
			solution.append(solStack.pop());
		}

	    return list;
	}
	
	
	public static boolean isPrime(long num) {
        if (num < 0) {
            return false;
        }
        if (num == 0 || num == 1) {
            return false;
        }
        if (num == 2 || num == 3) {
            return true;
        }

        for (long i = 2; i <=Math.sqrt(num); i++) {
			if (num % i == 0)
			{
				return false;
			}
		}
        return true;
    }
	
	public static ArrayList<Long> getfactors(long num) {
		ArrayList<Long> factors = new ArrayList<Long>();
		if(num>3)
		{
			for (long i = 2; i <=Math.sqrt(num); i++) {
				if (num % i == 0) {
					factors.add(i);
					if(num/i != i)
						factors.add(num/i);
				}
			}
		}
		return factors;
    }

	public static ArrayList<Long> getmultipliers(long numberToMultiply, long biggestNumerator)
	{
		ArrayList<Long> multipliers = new ArrayList<Long>();
		int i = 1;
		while(i*numberToMultiply <= biggestNumerator)
		{
			multipliers.add(i++*numberToMultiply);
		}
		return multipliers;
	}
	

}
